package tutorial.main.vista;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import tutorial.entidades.Evento;
import tutorial.main.R;
import tutorial.main.control.NetChangeService;
import tutorial.main.control.Notificable;
import tutorial.main.control.location.LocationFinder;
import tutorial.main.data.GestorBDLista;
import tutorial.main.data.ProviderRegistro;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.location.LocationListener;

import com.google.android.maps.MapView.LayoutParams;  

import android.text.format.DateFormat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;


public class MapsActivity extends MapActivity implements Notificable
{
	MapView mapView; 
	MapController mc;
    GeoPoint p;
    LocationFinder lf;
    MapsOverlayPins pinMiPosicion;
    MapsOverlayPins pinConexiones;
    MapsOverlayPins pinDesConexiones;
    
    boolean isCenterOnMyPosition;
    
    private int id_usuario;
    
    final int MAP_DEFAULT_ZOOM = 18; 
    
    static final int id_dialog_gps_off=0;
    

    
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.map);
        
        //bindService(new Intent(GrillaDeEstados.this, NetChangeService.class), mConnection,	0);
        
        isCenterOnMyPosition = true;
        
        // Obtengo el identificador del usuario que me pasa el intent
        this.id_usuario = getIntent().getExtras().getInt("id_usuario");
        
        turnGPSOnOff();
        
        lf = new LocationFinder(this);
        try
        {
        	lf.startListening(locListener);
        }
        catch(Exception e)
        {
        	Log.i(LOCATION_SERVICE,"El GPS NO ESTA ENCENDIDO");
        	showDialog(id_dialog_gps_off);
        }
        
        
        mapView = (MapView) findViewById(R.id.mapView);
        mapView.setStreetView(true);
        
        LinearLayout zoomLayout = (LinearLayout)findViewById(R.id.zoom);  
        View zoomView = mapView.getZoomControls(); 
        
        zoomLayout.addView(zoomView, 
            new LinearLayout.LayoutParams(
                LayoutParams.WRAP_CONTENT, 
                LayoutParams.WRAP_CONTENT)); 
        mapView.displayZoomControls(true);

        mc = mapView.getController();
        mc.setZoom(MAP_DEFAULT_ZOOM);

        // SETEO EL PIN DE MI POSICION
        Drawable drawable = this.getResources().getDrawable(R.drawable.pin_private);
        pinMiPosicion = new MapsOverlayPins(drawable,this);
        
        // SETEO LOS PINES DE LAS CONEXIONES
        Drawable drawableConx = this.getResources().getDrawable(R.drawable.pin_con);
        pinConexiones = new MapsOverlayPins(drawableConx,this);
        
        // SETEO LOS PINES DE LAS DESCONEXIONES
        Drawable drawableDesConx = this.getResources().getDrawable(R.drawable.pin_descon);
        pinDesConexiones = new MapsOverlayPins(drawableDesConx,this);
        
        // ACTUALIZO/ CREO EL PIN CON MI POSICION
        GeoPoint plf = lf.getLastPosition();
        if(plf!=null)
        {
        	updateUserLocation(plf);
        }
        
        // LLENO LOS OTROS PINES
        loadPinesConexion();
    }
    
	@Override
	protected void onResume() 
	{	
		super.onResume();
		Log.v("MapsActivity","onResume");
		bindService(new Intent(MapsActivity.this, NetChangeService.class), mConnection,	0);
	}
	
	@Override
	protected void onPause() 
	{
		super.onPause();
		unbindService(mConnection);
	};
    
    private void loadPinesConexion() 
    {
    	ArrayList<Evento> lista = GestorBDLista.cargaEventosPrevios(ProviderRegistro.CONTENT_URI,this,this.id_usuario);
    	
    	for (int i = 0; i < lista.size(); i++) 
    	{
    		Evento e = lista.get(i);
    		if(e.getPosicionLatitud()!=0 && e.getPosicionLongitud()!=0)
    		{
    				GeoPoint point = e.getPosicion();
    				CharSequence fecha = DateFormat.format("dd/M/yyyy kk:mm:ss", e.getMomento());
		    		if(e.getEstadoConetado())
		    		{
		    			// Es un pin de conexion
		    			Log.i("MapsActivity","Agrego un Pin de Conexion:"+i);
		    			OverlayItem miNuevoPin = new OverlayItem(point,"Conexión: "+e.getTipoConexion(),point.getLatitudeE6()+"|"+point.getLongitudeE6()+"\n"+fecha);
		    			pinConexiones.addOverlay(miNuevoPin);
		    		}
		    		else
		    		{
		    			// Es un pin de desconexion
		    			Log.i("MapsActivity","Agrego un Pin de DesConexion:"+i);
		    			OverlayItem miNuevoPin = new OverlayItem(point,"Desconexión: "+e.getTipoConexion(),point.getLatitudeE6()+"|"+point.getLongitudeE6()+"\n"+fecha);
		    			pinDesConexiones.addOverlay(miNuevoPin);		    			
		    		}
    		}
    		else
    		{
    			Log.i("MapsActivity","El pin "+i+" no tiene información sobre la conexion");
    		}
		}
    	
    	List<Overlay> mapOverlays = mapView.getOverlays();
    	mapOverlays.add(pinConexiones);
    	mapOverlays.add(pinDesConexiones);
		
	}

	private void updateUserLocation(GeoPoint point)
    {
    	Log.i("MapsActivity","Tu posición Actual:"+point.getLatitudeE6()+"/"+point.getLongitudeE6());
    	
    	OverlayItem miNuevoPin = new OverlayItem(point, "Tu posición Actual:",point.getLatitudeE6()+"/"+point.getLongitudeE6());
    	
    	Log.i("MapsActivity","SIZE DE LA COLEXION="+pinMiPosicion.size());
    	if(pinMiPosicion.size()==0)
    	{
    		// Aún no tengo mi pin puesto
    		pinMiPosicion.addOverlay(miNuevoPin);
    	}
    	else
    	{
    		// Ya lo tengo, lo reemplazo
    		pinMiPosicion.replaceFirst(miNuevoPin);
    	}
    	
    	 List<Overlay> mapOverlays = mapView.getOverlays();
    	 
    	 Log.i("MapsActivity","SIZE DE mapOverlays="+mapOverlays.size());
    	 
    	 if(!mapOverlays.isEmpty())
    	 {
    		 mapOverlays.remove(0);
    	 }
    	 mapOverlays.add(0,pinMiPosicion);	
    	 
    	 if(isCenterOnMyPosition)
    	 {
	         mc.animateTo(point);
	         mc.setZoom(15); 
	         mapView.invalidate();
    	 }
    	 
    }
    
   
    private GeoPoint locationToGeoPoint(Location loc)
    {
    	return new GeoPoint(
                (int) (loc.getLatitude() * 1E6), 
                (int) (loc.getLongitude() * 1E6));
    }
 
    @Override
    protected boolean isRouteDisplayed() {
        return false;
    }
    
    //Creacion de dialogos segun su tipo
  	@Override
      protected Dialog onCreateDialog(int id)
      {
      	Dialog dialogo= null;
      	switch(id) {
          case id_dialog_gps_off:
              dialogo=crearDialogoGPSOff();
              break;       
          default:
              dialogo = null;
          }

      	return dialogo;
      }    
    
	private Dialog crearDialogoGPSOff() 
	{
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
    	builder.setMessage(getString(R.string.msj_gps_off));
    	builder.setNeutralButton(getString(R.string.aceptar), null);    	
    	AlertDialog dialogo = builder.create();
    	return dialogo;	
	}
	
	
	/**
	 * Obtiene la lista de eventos que hay que mostrar en el mapa
	 * @return
	 */
	private ArrayList<Evento> getEventsStub()
	{
		ArrayList<Evento> listaSinFiltrar = GestorBDLista.cargaEventosPrevios(ProviderRegistro.CONTENT_URI,this,id_usuario); 
		ArrayList<Evento> lista = new ArrayList<Evento>();
		
		for (int i = 0; i < listaSinFiltrar.size(); i++) 
		{
			Evento e = listaSinFiltrar.get(i);
			
			if(e.getPosicionLatitud()!=0 && e.getPosicionLongitud()!=0)
			{
				// El evento tiene coordenadas GPS
				lista.add(e);
			}
			
		}
		Log.i("MapsActivity","LISTA DE EVENTOS AL MAPA SIN FILTRAR:"+listaSinFiltrar.size());
		Log.i("MapsActivity","LISTA DE EVENTOS AL MAPA CON FILTRO :"+lista.size());
		
		return lista;
		
	}
	
	private void turnGPSOnOff()
	{
		  String provider = Settings.Secure.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
		  if(!provider.contains("gps"))
		  {
		    final Intent poke = new Intent();
		    poke.setClassName("com.android.settings", "com.android.settings.widget.SettingsAppWidgetProvider");
		    poke.addCategory(Intent.CATEGORY_ALTERNATIVE);
		    poke.setData(Uri.parse("3")); 
		    sendBroadcast(poke);
		    //Toast.makeText(this, "Your GPS is Enabled",Toast.LENGTH_SHORT).show();
		  }
	}
	
	@Override
	public boolean onPrepareOptionsMenu(Menu menu) 
	{
		menu.clear();
		MenuInflater inflater = new MenuInflater(this);
		inflater.inflate(R.menu.map_menu, menu);
		
		MenuItem item = menu.findItem(R.id.menu_mapa_centrar_posicion);
		if(isCenterOnMyPosition)
		{
			item.setTitle(R.string.i_mapa_no_centrado);
			item.setIcon(R.drawable.ic_menu_mylocation);
		}
		else
		{
			item.setTitle(R.string.i_mapa_centrado);
			item.setIcon(R.drawable.ic_menu_nomylocation);
		}
		
		return true;
	}
	
	public boolean onMenuItemSelected(int featureId, MenuItem item) 
	{
		switch (item.getItemId()) 
		{
			case R.id.menu_mapa_centrar_posicion:
				
				if(isCenterOnMyPosition)
				{
					isCenterOnMyPosition = false;
				}
				else
				{
					isCenterOnMyPosition = true;
				}
				return true;
		}
		Log.i("MapsActicity","Is Center On My Position?: "+isCenterOnMyPosition);
		return false;
	}	
	
	

	LocationListener locListener = new LocationListener()
	{
		//  Lanzado cada vez que se recibe una actualización de la posición
		@Override
	    public void onLocationChanged(Location location) {
	    	Log.i(LOCATION_SERVICE, "CAMBIO DE LOCALIZACION:"+location.getLatitude()+"|"+location.getLongitude());
	    	updateUserLocation(locationToGeoPoint(location));
	    }
	 
	    //  Lanzado cuando el proveedor se deshabilita.
		@Override
	    public void onProviderDisabled(String provider){
	        
	    }
	 
	    //  Lanzado cuando el proveedor se habilita.
		@Override
	    public void onProviderEnabled(String provider){
	        
	    }
	 
	    // Lanzado cada vez que el proveedor cambia su estado, que puede variar entre OUT_OF_SERVICE, TEMPORARILY_UNAVAILABLE, AVAILABLE.
		@Override
	    public void onStatusChanged(String provider, int status, Bundle extras){
	        
	    }
	};
	
    private NetChangeService ncservice;
    final ServiceConnection mConnection = new ServiceConnection()
    {
       public void onServiceConnected(ComponentName className, IBinder service)
       {
           ncservice = ((NetChangeService.LocalBinder) service).getService();
           ncservice.RegisterNotificable(MapsActivity.this);
       }

        public void onServiceDisconnected(ComponentName className)
        {
           ncservice = null;
        }
    };    
    
    public NetChangeService getNetChangeService()
    {
       return ncservice;
    }

	
	/**
	* Se detecto un cambio de conexion, tengo que avisar al mapa para que agregue el PIN
	* a donde corresponda
	*/
    @Override
	public boolean notificar(Evento e)
	{
	   // Agregar este evento al mapa si tengo las coordenadas!!
		if(e.getPosicionLatitud()!=0 && e.getPosicionLongitud()!=0)
		{
		  GeoPoint point = e.getPosicion();
		  CharSequence fecha = DateFormat.format("dd/M/yyyy kk:mm:ss", e.getMomento());
		     if(e.getEstadoConetado())
		     {
		          // Es de conexion
		    	 Log.i("MapsActivity","Agrego un Pin de Conexion por cambio de Evento");
		    	 OverlayItem miNuevoPin = new OverlayItem(point,"Conexión: "+e.getTipoConexion(),point.getLatitudeE6()+"|"+point.getLongitudeE6()+"\n"+fecha);
		         pinConexiones.addOverlay(miNuevoPin);
		     }
		     else
		     {
		          // Es de desconexion
		    	 Log.i("MapsActivity","Agrego un Pin de DesConexion por cambio de Evento");
		    	 OverlayItem miNuevoPin = new OverlayItem(point,"Desconexión: "+e.getTipoConexion(),point.getLatitudeE6()+"|"+point.getLongitudeE6()+"\n"+fecha);
		         pinDesConexiones.addOverlay(miNuevoPin);
		     }

		     // Muestro un mensaje avisando que se agrego el evento.
		     String titulo  = getString(R.string.i_not_nuevoEvento);
		     String mensaje = e.getPosicionLatitud()+"|"+e.getPosicionLongitud()+"\n"+fecha;
		     showMessageToast(this,titulo,mensaje);
		 }

		return true;
	}
    
    private void showMessageToast(Context ctx,String titulo,String message)
    {
    	Toast toastNewEvent = new Toast(ctx);
		 
		MapActivity ma = (MapActivity)ctx;
        LayoutInflater inflater = ma.getLayoutInflater();
        View layout = inflater.inflate(R.layout.map_toast_layout,(ViewGroup) ma.findViewById(R.id.layout_root));
 
        TextView txtTipoConexion = (TextView)layout.findViewById(R.id.txtTipoConexion);
        txtTipoConexion.setText(titulo);
 
        TextView txtLocation = (TextView)layout.findViewById(R.id.txtLocation);
        txtLocation.setText(message);
        
        toastNewEvent.setDuration(Toast.LENGTH_LONG);
        toastNewEvent.setView(layout);
        toastNewEvent.show();
    }
	
}
